package pl.umk.mat.fred.unicore.urc.storagemanagement.tree.utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IllegalFormatException;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.util.URIUtil;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.unigrids.services.atomic.types.GridFileType;
import org.unigrids.services.atomic.types.PermissionsType;

import de.fzj.unicore.uas.client.StorageClient;
import de.fzj.unicore.wsrflite.xmlbeans.BaseFault;

import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.BelowStorageNode.OldPermissions;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.CatalogNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.FileNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.MultiplyCatalogNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.Node;

public class TreeUtils {

	public static void addGridFileTypes(Node parent, GridFileType[] files) {
		for (GridFileType file : files) {
			if (file.getIsDirectory()) {
				CatalogNode node = new CatalogNode();
				node.setParent(parent);
				node.setLastModified(file.getLastModified());
				node.setPath(file.getPath());
				node.setOwner(file.getOwner());
				PermissionsType permissionsType = file.getPermissions();
				if (permissionsType != null) {
					OldPermissions permissions = new OldPermissions(permissionsType.getReadable(), permissionsType.getWritable(), permissionsType.getExecutable());
					node.setPermissions(permissions);
				}
				node.setPermissions(file.getFilePermissions());
				parent.add(node);
			} else {
				FileNode node = new FileNode();
				node.setFileSize(file.getSize());
				node.setParent(parent);
				node.setLastModified(file.getLastModified());
				node.setPath(file.getPath());
				node.setOwner(file.getOwner());
				PermissionsType permissionsType = file.getPermissions();
				if (permissionsType != null) {
					OldPermissions permissions = new OldPermissions(permissionsType.getReadable(), permissionsType.getWritable(), permissionsType.getExecutable());
					node.setPermissions(permissions);
				}
				node.setPermissions(file.getFilePermissions());
				parent.add(node);
			}
		}
	}
	
	public static void removeNode(Node node) {
		Node parent = node.getParent();
		parent.getChildren().remove(node);
	}
	
	public static String getNameFromPath(String path) {
		int pos = path.lastIndexOf("/");
		if (pos == -1) {
			return path;
		}
		return path.substring(pos + 1);
	}
	
	public static int getSelectedFilesSize(IStructuredSelection selection) {
		int counter = 0;
		for (Object obj : selection.toArray()) {
			StorageClient client = null;
			if (obj instanceof FileNode) {
				FileNode node = (FileNode) obj;
				client = node.getStorage().getClient();
				synchronized (client) {
					try {
						counter += client.getExport(URIUtil.encode(node.getPath(), org.apache.commons.httpclient.URI.allowed_fragment)).getSize();
					} catch (URIException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			} else if (obj instanceof CatalogNode) {
				CatalogNode node = (CatalogNode) obj;
				counter += getCatalogSize(node.getStorage().getClient(), node.getPath());
			}
		}
		return counter;
	}
	
	private static int getCatalogSize(StorageClient client, String remotePath) {
		int counter = 0;
		GridFileType[] gft = null;
		synchronized (client) {
			try {
				gft = client.listDirectory(URIUtil.encode(remotePath, org.apache.commons.httpclient.URI.allowed_fragment));
			} catch (URIException e) {
				e.printStackTrace();
			} catch (BaseFault e) {
				e.printStackTrace();
			}
		}
		if (gft != null) {
			for (GridFileType g : gft) {
				if (g.getIsDirectory()) {
					counter += getCatalogSize(client, g.getPath());
				} else {
					counter += g.getSize();
				}
			}
		}
		return counter;
	}
	
	public static List<Node> getMergedChildList(List<Node> children){
		List<Node> result = new ArrayList<Node>();
		Map<String, MultiplyCatalogNode> multiplyCatalogs = new HashMap<String, MultiplyCatalogNode>();
		
		for (Node n1 : children) {
			boolean addNode = true;
			for (Node n2 : new ArrayList<Node>(children)) {
				if (!n1.equals(n2)) {
					if ((n1 instanceof FileNode) && (n2 instanceof FileNode)) {
						FileNode fn1 = (FileNode) n1;
						FileNode fn2 = (FileNode) n2;
						if (fn1.getNameWithoutSuffix().equals(fn2.getNameWithoutSuffix())) {
							fn1.setPrintSuffix(true);
							fn2.setPrintSuffix(true);
						}
					} else if ((n1 instanceof CatalogNode) && (n2 instanceof CatalogNode)) {
						CatalogNode cn1 = (CatalogNode) n1;
						CatalogNode cn2 = (CatalogNode) n2;
						if (cn1.getName().equals(cn2.getName())) {
							addNode = false;
							MultiplyCatalogNode multi =  multiplyCatalogs.get(cn1.getName());
							if (multi == null) {
								multi = new MultiplyCatalogNode();
								multiplyCatalogs.put(cn1.getName(), multi);
								result.add(multi);
							}
							if (!cn1.hasSiblings()) {
								multi.addCatalog(cn1);
								cn1.setHasSiblings(true);
								cn1.setMultiplyCatalogNode(multi);
							}
							if (!cn2.hasSiblings()) {
								multi.addCatalog(cn2);
								cn2.setHasSiblings(true);
								cn2.setMultiplyCatalogNode(multi);
							}
						}
					}
				}
			}
			if (addNode) {
				if (n1 instanceof CatalogNode) {
					((CatalogNode) n1).setMultiplyCatalogNode(null);
				}
				result.add(n1);
			}
		}
		for (Node n1 : children) {
			if (n1 instanceof CatalogNode) {
				((CatalogNode) n1).setHasSiblings(false);
			}
		}
		return result;
	}
	
	public static String formatStorageSpace(Long s) {
		String[] UNIT = {"B", "KB", "MB", "GB"};
		Long space = new Long(s);
		int unit = 0;
		int stop = (UNIT.length - 1);
		while ((unit < stop) && (space >= 1024)) {
			space = space / 1024;
			unit++;
		}
		return space + " " + UNIT[unit];
	}
	
	public static String parseUser(String subjectDN) {
		int start = -1;
		int end = -1;
		start = subjectDN.indexOf("CN=");
		if (start == -1) {
			start = subjectDN.indexOf("cn=");
		}
		end = subjectDN.indexOf(",", start + 3);
		if (start != -1) {
			if (end != -1) {
				return subjectDN.substring(start + 3, end);
			} else {
				return subjectDN.substring(start + 3);
			}
		}
		return null;
	}
	
	public static int compareServerVerions(String v1, String v2) throws NumberFormatException {
		String[] vTab1 = v1.split(".");
		String[] vTab2 = v2.split(".");
		int i = 0;
		while (i < vTab1.length && i < vTab2.length) {
			int n1 = Integer.valueOf(vTab1[i]);
			int n2 = Integer.valueOf(vTab2[i]);
			if (n1 > n2) {
				return 1;
			} else if (n2 < n1) {
				return -1;
			}
			i++;
		}
		if (vTab1.length > vTab2.length) {
			return 1;
		} else if (vTab1.length < vTab2.length) {
			return -1;
		}
		
		return 0;
	}
	
}
